package top.haijunit.navi.auth.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import top.haijunit.framework.core.domain.QueryPage;
import top.haijunit.framework.core.domain.ResultPage;
import top.haijunit.framework.core.exception.ExceptionServer;
import top.haijunit.framework.core.util.CollectionUtils;
import top.haijunit.navi.auth.domain.PermissionMerge;
import top.haijunit.navi.auth.domain.RoleConvert;
import top.haijunit.navi.auth.domain.RoleInfo;
import top.haijunit.navi.auth.entity.RoleEntity;
import top.haijunit.navi.auth.mapper.RoleMapper;

import java.util.*;

/**
 * 角色服务
 *
 * @author zhanghaijun
 * @since 2024-08-30
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__({@Autowired}))
public class RoleService extends ServiceImpl<RoleMapper, RoleEntity> {

    private final PermissionService permissionService;
    private final RolePermissionService rolePermissionService;
    private final RoleConvert converter;

    /**
     * 查询条件
     */
    private static LambdaQueryWrapper<RoleEntity> queryConditional(RoleInfo info) {
        LambdaQueryWrapper<RoleEntity> query = new LambdaQueryWrapper<>();
        if (info != null) {
            query.like(CharSequenceUtil.isNotBlank(info.getRoleName()), RoleEntity::getRoleName, info.getRoleName());
        }
        query.orderByAsc(RoleEntity::getRoleLevel).orderByAsc(RoleEntity::getRoleName);
        return query;
    }

    /**
     * 获取角色分页
     */
    public ResultPage<RoleInfo> selectPageList(QueryPage queryPage, RoleInfo info) {
        Page<RoleEntity> entityPage = this.baseMapper.selectPage(new Page<>(Math.max(1, queryPage.getPage()), Math.max(1, queryPage.getSize())), queryConditional(info));
        return ResultPage.build(entityPage, converter::convertPost);
    }

    /**
     * 获取角色列表
     */
    public Collection<RoleInfo> selectList(RoleInfo info) {
        List<RoleEntity> entityList = this.baseMapper.selectList(queryConditional(info));
        return converter.convertPost(entityList);
    }

    /**
     * 获取角色详情
     */
    public RoleInfo selectDetail(Long code) {
        LambdaQueryWrapper<RoleEntity> query = new LambdaQueryWrapper<>();
        query.eq(RoleEntity::getRoleId, code);
        List<RoleEntity> entityList = this.baseMapper.selectList(query);
        if (CollUtil.isEmpty(entityList)) {
            throw new ExceptionServer("角色不存在");
        }
        if (entityList.size() > 1) {
            log.error("数据库数据异常，存在重复的异常数据: {} 重复", code);
        }
        RoleEntity entity = CollUtil.getFirst(entityList);
        return converter.convert(entity, getRolePermissionMap(Collections.singletonList(entity.getRoleId())));
    }

    /**
     * 添加角色
     */
    public Long insert(RoleInfo role) {
        // 检查权限之间是否存在冲突，如果存在冲突，则抛出异常
        Assert.notEmpty(role.getPermissionMap(), "权限配置不能为空！");
        permissionService.checkPermissionConflicts(role.getPermissionMap().keySet());
        Assert.hasLength(role.getRoleName(), "角色名称不能为空");
        LambdaQueryWrapper<RoleEntity> query = new LambdaQueryWrapper<>();
        query.eq(RoleEntity::getRoleName, role.getRoleName());
        if (this.exists(query)) {
            throw new ExceptionServer("角色名称已存在，请更换名称！");
        }
        RoleEntity entity = converter.convert(role);
        this.baseMapper.insert(entity);
        // 保存角色权限
        rolePermissionService.updateRolePermission(entity.getRoleId(), role.getPermissionMap());
        // 返回角色编号
        return entity.getRoleId();
    }

    /**
     * 修改角色
     */
    public Long modify(RoleInfo role) {
        // 检查权限之间是否存在冲突，如果存在冲突，则抛出异常
        Assert.notEmpty(role.getPermissionMap(), "权限配置不能为空！");
        permissionService.checkPermissionConflicts(role.getPermissionMap().keySet());
        // 检查角色是否存在
        Assert.hasLength(role.getRoleId(), "修改的角色不存在");
        if (!baseMapper.exists(new LambdaQueryWrapper<RoleEntity>().eq(RoleEntity::getRoleId, role.getRoleId()))) {
            throw new ExceptionServer("修改的角色已失效");
        }
        // 判断角色名称是否重复，如果存在则抛出异常
        Assert.hasLength(role.getRoleName(), "角色名称不能为空");
        LambdaQueryWrapper<RoleEntity> query = new LambdaQueryWrapper<>();
        query.ne(RoleEntity::getRoleId, role.getRoleId());
        query.eq(RoleEntity::getRoleName, role.getRoleName());
        if (this.exists(query)) {
            throw new ExceptionServer("角色名称已存在，请更换名称！");
        }
        // 修改角色
        RoleEntity entity = converter.convert(role);
        Assert.notNull(entity.getRoleId(), "修改的角色不存在");
        LambdaQueryWrapper<RoleEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleEntity::getRoleId, entity.getRoleId());
        this.baseMapper.update(entity, wrapper);
        // 保存角色权限
        rolePermissionService.updateRolePermission(entity.getRoleId(), role.getPermissionMap());
        // 返回角色编号
        return entity.getRoleId();
    }

    /**
     * 删除角色
     */
    public Long delete(Long code) {
        LambdaQueryWrapper<RoleEntity> query = new LambdaQueryWrapper<>();
        query.eq(RoleEntity::getRoleId, code);
        this.baseMapper.delete(query);
        return code;
    }

    /**
     * 获取角色权限
     */
    Map<Long, Integer> getRolePermissionMap(List<Long> roleCodes) {
        if (null == roleCodes || roleCodes.isEmpty()) {
            return new HashMap<>();
        }
        List<PermissionMerge> permissionMergeList = baseMapper.selectRolePermissionByRoleId(roleCodes);
        if (permissionMergeList == null) {
            return new HashMap<>();
        }
        // 权限的合并，先排序，合并冲突取前面的。
        return CollectionUtils.toMap(CollUtil.sort(permissionMergeList, PermissionMerge::compareTo), PermissionMerge::getPermissionCode, PermissionMerge::getPermissionStatus, (oldValue, newValue) -> newValue);
    }

    /**
     * 获取有效的权限集合
     */
    public List<Long> getRolePermissionCodes(List<Long> roleCodes) {
        Map<Long, Integer> permissionMap = getRolePermissionMap(roleCodes);
        List<Long> validPermissionCodes = new ArrayList<>();
        for (Map.Entry<Long, Integer> entry : permissionMap.entrySet()) {
            if (Integer.valueOf(1).equals(entry.getValue())) {
                validPermissionCodes.add(entry.getKey());
            }
        }
        return validPermissionCodes;
    }

    /**
     * 判断角色是否拥有权限
     */
    public boolean roleHasPermission(Long roleCode, Long... permissionCode) {
        Map<Long, Integer> permissionMap = getRolePermissionMap(Collections.singletonList(roleCode));
        for (Long permission : permissionCode) {
            if (!permissionMap.containsKey(permission) || permissionMap.get(permission) != 0) {
                return false;
            }
        }
        return true;
    }
}
